package com.cyanite.playlv2;

import com.cyanite.playlv2.util.NotificationsUtil;
import com.cyanite.playlv2.widget.MessageAdapter;
import com.cyanite.playlv2.widget.SegmentedButton;
import com.cyanite.playlv2.widget.SegmentedButton.OnClickListenerSegmentedButton;
import com.cyanite.playlv2api.types.Group;
import com.cyanite.playlv2api.types.Message;
import com.cyanite.playlv2api.types.Response;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

public class MessageActivity extends Activity{

    public static final String EXTRA_NEW_MESSAGE_COUNT = PlayLv2.PACKAGE_NAME
        + ".MessageActivity.EXTRA_NEW_MESSAGE_COUNT";

    private ListView mMsgsListView;
    private MessageAdapter mMsgsAdapter;
    private StateHolder mStateHolder;
    private ProgressDialog mDlgProgress;
    private int mItemClicked;
    private View mViewProgressBar;
    private AlertDialog mAlertDlg;

    private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            finish();
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.message_activity);
        registerReceiver(mLoggedOutReceiver, new IntentFilter(PlayLv2.INTENT_ACTION_LOGGED_OUT));

        mStateHolder = new StateHolder();
        if (getIntent().hasExtra(EXTRA_NEW_MESSAGE_COUNT)) {
            mStateHolder.setMsgsNewCount(getIntent().getExtras().getInt(EXTRA_NEW_MESSAGE_COUNT));
        }

        mViewProgressBar = findViewById(R.id.messageProgress);
        mViewProgressBar.setVisibility(View.VISIBLE);
        // Loading inbox msgs by default
        mStateHolder.startTaskGetMessages(this);
        ensureUi();
    }

    private void ensureUi() {

        setTitle(getString(R.string.message_activity_label));

        mMsgsListView = (ListView)findViewById(R.id.lvMessageListView);
        SegmentedButton btnType = (SegmentedButton)findViewById(R.id.btnMessageSegmented);
        btnType.clearButtons();
        btnType.addButtons(this.getString(R.string.message_segment_button_inbox),
                                               this.getString(R.string.message_segment_button_system));

        btnType.setOnClickListener(new OnClickListenerSegmentedButton() {
            @Override
            public void onClick(int index) {
                switch(index){
                    case 0:
                        mStateHolder.setIsInbox(true);
                        updateUi();
                        break;
                    case 1:
                        mStateHolder.setIsInbox(false);
                        if ( !mStateHolder.getIsGetSysMsgs() ) {
                            mStateHolder.setIsGetSysMsgs(true);
                            mStateHolder.startTaskGetMessages( MessageActivity.this );
                        }
                        updateUi();
                        break;
                    default:
                        break;
                }
            }
        });

        updateUi();
    }

    private void updateUi() {
        Group<Message> msgs = mStateHolder.getMsgs();
        if ( msgs != null && msgs.size() > 0 ) {
            mMsgsAdapter = new MessageAdapter( this, msgs, mButtonRowClickHandler);
            mMsgsListView.setAdapter(mMsgsAdapter);
        }   else {
            mMsgsListView.setAdapter(null);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            Bundle bundle = new Bundle();
            bundle.putInt("newsleft", mStateHolder.getMsgsNewCount());
            setResult(RESULT_OK, this.getIntent().putExtras(bundle));
            finish();
            return true;
        }else {
            return super.onKeyDown(keyCode, event);
        }
    }

    private MessageAdapter.ButtonRowClickHandler mButtonRowClickHandler =
        new MessageAdapter.ButtonRowClickHandler (){
            @Override
            public void onBtnClickDelete(int position) {
                startProgressBar(getResources().getString(R.string.message_activity_label),
                        getResources().getString(R.string.message_send_delete_progress_post));
                mItemClicked = position;
                mStateHolder.startTaskDeleteMessage(MessageActivity.this, position);
            }

            public void onBtnClickInfo(int position)   {
                startProgressBar(getResources().getString(R.string.message_activity_label),
                        getResources().getString(R.string.message_send_open_progress_post));
                mItemClicked = position;
                mStateHolder.startTaskGetMessageContent(MessageActivity.this, position);
            }
    };

    protected void popUpMessageDialog() {
        LayoutInflater factory = LayoutInflater.from(MessageActivity.this);
        final View textEntryView = factory.inflate(R.layout.message_content_dialog, null);
        mAlertDlg = new AlertDialog.Builder(MessageActivity.this)
        .setTitle(this.getString(R.string.message_activity_label))
        .setView(textEntryView)
        .create();

        Message msg = mStateHolder.getReadedMsg();
        TextView userName = (TextView)textEntryView.findViewById(R.id.tvMessageUserName);
        userName.setText(this.getResources().getString(R.string.friend_requests_approved) + msg.getUserName());
        userName.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MessageActivity.this, UserDetailsActivity.class);
                intent.putExtra(UserDetailsActivity.EXTRA_USER_ID, mStateHolder.getReadedMsg().getUserId());
                startActivity(intent);
                mAlertDlg.dismiss();
            }
        });

        Button btnOk = (Button)textEntryView.findViewById(R.id.btnMessageOk);
        btnOk.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                mAlertDlg.dismiss();
             }
         });
        TextView tripName = (TextView)textEntryView.findViewById(R.id.tvMessageTrip);
        tripName.setText(msg.getTripName());
        tripName.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MessageActivity.this, TripDetailsActivity.class);
                intent.putExtra(TripDetailsActivity.EXTRA_TRIP_ID, mStateHolder.getReadedMsg().getTripId());
                startActivity(intent);
                mAlertDlg.dismiss();
            }
        });
        mAlertDlg.show();
    }

    private void startProgressBar(String title, String message) {
        if (mDlgProgress == null) {
            mDlgProgress = ProgressDialog.show(this, title, message);
        }
        mDlgProgress.show();
    }

    private void stopProgressBar() {
        if (mDlgProgress != null) {
            mDlgProgress.dismiss();
            mDlgProgress = null;
        }
    }

    private void onGetMessagesTaskComplete(Group<Message> msgs, boolean isInbox, Exception ex) {
        mViewProgressBar.setVisibility(View.GONE);
        if (isInbox) {
            mStateHolder.setMsgsInbox(msgs);
        }   else {
            mStateHolder.setMsgsSys(msgs);
        }
        updateUi();
    }

    private static class GetMessagesTask extends AsyncTask<Void, Void, Group<Message>> {

        private MessageActivity mActivity;
        private Exception mReason;
        private boolean mIsInbox;

        public GetMessagesTask(MessageActivity activity, boolean isInbox) {
            mActivity = activity;
            mIsInbox = isInbox;
        }

        @Override
        protected Group<Message> doInBackground(Void... params) {
            try {
                return ((PlayLv2) mActivity.getApplication()).getPlayLv2Api().messages(mIsInbox);
                } catch (Exception ex) {
                mReason = ex;
                return null;
            }
        }

        @Override
        protected void onPostExecute(Group<Message> msgs) {
            if (mActivity != null) {
                mActivity.onGetMessagesTaskComplete(msgs, mIsInbox, mReason);
            }
        }

        protected void onCancelled() {
            if (mActivity != null) {
                mActivity.onGetMessagesTaskComplete(null, false, new Exception(
                        "Messages loading cancelled."));
            }
        }
    }

    private void onGetMessageContentTaskComplete(Message msg, Exception ex) {
        stopProgressBar();
        if ( msg != null ) {
            boolean isReaded = mStateHolder.getMsgs().get(mItemClicked).getIsReaded();
            if ( !isReaded )  {
                mStateHolder.getMsgs().get(mItemClicked).setIsReaded(true);
                mMsgsAdapter = new MessageAdapter( this, mStateHolder.getMsgs(), mButtonRowClickHandler );
                mMsgsListView.setAdapter(mMsgsAdapter);
            }
            mStateHolder.setReadedMsg(msg);
            if (msg.getTripId() != null && !msg.getTripId().equals(""))    {
                popUpMessageDialog();
            } else if (!msg.getUserId().equals("") && msg.getUserId() != null)  {
                Intent intent = new Intent(MessageActivity.this, UserDetailsActivity.class);
                intent.putExtra(UserDetailsActivity.EXTRA_USER_ID, msg.getUserId());
                startActivity(intent);
            }
        }
    }

    private static class GetMessageContentTask extends AsyncTask<Void, Void, Message> {

        private MessageActivity mActivity;
        private Exception mReason;
        private String mMsgId;

        public GetMessageContentTask(MessageActivity activity, String msgId) {
            mActivity = activity;
            mMsgId = msgId;
        }

        @Override
        protected Message doInBackground(Void... params) {
            try {
                return ((PlayLv2) mActivity.getApplication()).getPlayLv2Api().getMsgContent(mMsgId);
            } catch (Exception ex) {
                mReason = ex;
                return null;
            }
        }

        @Override
        protected void onPostExecute(Message msg) {
            if (mActivity != null) {
                mActivity.onGetMessageContentTaskComplete(msg, mReason);
            }
        }

        protected void onCancelled() {
            if (mActivity != null) {
                mActivity.onGetMessageContentTaskComplete(null, new Exception(
                        "Message require content cancelled."));
            }
        }
    }

    private void onDeleteMessageTaskComplete(Response response, Exception ex) {
        stopProgressBar();
        if ( response != null && response.getValue().equals("0") ) {
            mStateHolder.getMsgs().remove(mItemClicked);
            mMsgsAdapter = new MessageAdapter( MessageActivity.this, mStateHolder.getMsgs(), mButtonRowClickHandler );
            mMsgsListView.setAdapter(mMsgsAdapter);
        } else {
            NotificationsUtil.ToastReasonForFailure(this, ex);
        }
    }

    private static class DeleteMessageTask extends AsyncTask<Void, Void, Response> {

        private MessageActivity mActivity;
        private Exception mReason;
        private String mMsgId;

        public DeleteMessageTask(MessageActivity activity, String msgId) {
            mActivity = activity;
            mMsgId = msgId;
        }

        @Override
        protected Response doInBackground(Void... params) {
            try {
                Response response = ((PlayLv2) mActivity.getApplication()).getPlayLv2Api().deleteMsg(mMsgId);
                if (response == null)   response = new Response();
                return response;
            } catch (Exception ex) {
                mReason = ex;
                return null;
            }
        }

        @Override
        protected void onPostExecute(Response respons) {
            if (mActivity != null) {
                mActivity.onDeleteMessageTaskComplete(respons, mReason);
            }
        }

        protected void onCancelled() {
            if (mActivity != null) {
                mActivity.onDeleteMessageTaskComplete(null, new Exception(
                        "Delete Message cancelled."));
            }
        }
    }

    private static class StateHolder {
        private boolean mIsInbox;
        private int mMsgsNewCount;
        private Message mMsgReaded;
        private Group<Message> mInboxMsgs;
        private Group<Message> mSysMsgs;
        private GetMessagesTask mGetMessagesTask;
        private DeleteMessageTask mDeleteMessagesTask;
        private GetMessageContentTask mGetMessageContentTask;
        private boolean mIsGetSysMsgs;

        public StateHolder() {
            mIsInbox = true;
            mMsgsNewCount = 0;
            mIsGetSysMsgs = false;
        }

        void setMsgsNewCount(int count) {
            mMsgsNewCount = count;
        }

        int getMsgsNewCount()   {
            return mMsgsNewCount;
        }

        void setIsInbox(boolean isInbox)    {
            mIsInbox = isInbox;
        }

        boolean getIsGetSysMsgs()  {
            return mIsGetSysMsgs;
        }

        void setIsGetSysMsgs(boolean isGet) {
            mIsGetSysMsgs = isGet;
        }

        void setMsgsInbox(Group<Message> msgs)  {
            mInboxMsgs = msgs;
        }

        void setMsgsSys(Group<Message> msgs)  {
            mSysMsgs = msgs;
        }

        Message getReadedMsg()    {
            return mMsgReaded;
        }

        void setReadedMsg(Message msg)  {
            mMsgReaded.setTripId(msg.getTripId());
            mMsgReaded.setTripName(msg.getTripName());
            mMsgReaded.setUserId(msg.getUserId());
        }

        Group<Message> getMsgs()   {
            if ( mIsInbox ) {
                return mInboxMsgs;
            }   else {
                return mSysMsgs;
            }
        }

        public void startTaskGetMessages(MessageActivity activity) {
            mGetMessagesTask = new GetMessagesTask(activity, mIsInbox);
            mGetMessagesTask.execute();
        }

        public void startTaskDeleteMessage(MessageActivity activity, int position) {
            Message msg = getMsgs().get(position);
            if (!msg.getIsReaded())    {
                mMsgsNewCount--;
            }
            mDeleteMessagesTask = new DeleteMessageTask(activity, msg.getId());
            mDeleteMessagesTask.execute();
        }

        public void startTaskGetMessageContent(MessageActivity activity, int position) {
            mMsgReaded = getMsgs().get(position);
            if (!mMsgReaded.getIsReaded())    {
                mMsgsNewCount--;
            }
            mGetMessageContentTask = new GetMessageContentTask(activity, mMsgReaded.getId());
            mGetMessageContentTask.execute();
        }
    }
}
